home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / ulib14.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  19KB  |  488 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       u l i b 1 4 . c                                              */
  3. /*                                                                    */
  4. /*       Serial port communications driver for ARTICOMM INT14         */
  5. /*       driver                                                       */
  6. /*--------------------------------------------------------------------*/
  7.  
  8. /*--------------------------------------------------------------------*/
  9. /*    Copyright (c) Richard H. Lamb 1985-1987                         */
  10. /*                                                                    */
  11. /*    Changes Copyright 1992 by Mark W. Schumann                      */
  12. /*--------------------------------------------------------------------*/
  13.  
  14. /*--------------------------------------------------------------------*/
  15. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  16. /*    Wonderworks.                                                    */
  17. /*                                                                    */
  18. /*    All rights reserved except those explicitly granted by the      */
  19. /*    UUPC/extended license agreement.                                */
  20. /*--------------------------------------------------------------------*/
  21.  
  22. /*--------------------------------------------------------------------*/
  23. /*       This suite needs some tuning, but the Wonderworks lacks      */
  24. /*       the time and more importantly the software to do so.         */
  25. /*       Specific problems:                                           */
  26. /*                                                                    */
  27. /*          The INT14 interface is not checked to be ARTICOMM, and    */
  28. /*          thus the extensions to the generic INT14 functions may    */
  29. /*          fail with no warning to the user.                         */
  30. /*                                                                    */
  31. /*          Non-ARTICOMM programs are not supported.                  */
  32. /*                                                                    */
  33. /*          No error is returned if a write times out                 */
  34. /*                                                                    */
  35. /*          Input data is discarded if a read times out, which        */
  36. /*          will confuse the 'g' packet input processor.              */
  37. /*--------------------------------------------------------------------*/
  38.  
  39. /*--------------------------------------------------------------------*/
  40. /*                          RCS Information                           */
  41. /*--------------------------------------------------------------------*/
  42.  
  43. /*
  44.  *    $Id: ulib14.c 1.3 1993/10/03 22:09:09 ahd Exp $
  45.  *
  46.  *    $Log: ulib14.c $
  47.  * Revision 1.3  1993/10/03  22:09:09  ahd
  48.  * Use unsigned long to display speed
  49.  *
  50.  * Revision 1.2  1993/05/30  15:25:50  ahd
  51.  * Multiple driver support
  52.  *
  53.  *
  54.  *   30 Nov 92 - Adapt for use with INT14 drivers.
  55.  *               Currently this is guaranteed to work only with
  56.  *               Artisoft's ARTICOMM driver, but porting to others
  57.  *               should be minor.  Mods by Mark W. Schumann
  58.  *               <mark@whizbang.wariat.org>
  59.  */
  60.  
  61. /*--------------------------------------------------------------------*/
  62. /*                        System include files                        */
  63. /*--------------------------------------------------------------------*/
  64.  
  65. #include <fcntl.h>
  66. #include <io.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <time.h>
  71.  
  72. #include <dos.h>    /* Declares union REGS and int86(). */
  73.  
  74. /*--------------------------------------------------------------------*/
  75. /*                    UUPC/extended include files                     */
  76. /*--------------------------------------------------------------------*/
  77.  
  78. #include "lib.h"
  79. #include "hlib.h"
  80. #include "ulib.h"
  81. #include "comm.h"          // Modem status bits
  82. #include "ssleep.h"
  83. #include "catcher.h"
  84.  
  85. #include "fossil.h"        // Various INT14 definitions
  86. #include "commlib.h"       // Trace functions, etc.
  87.  
  88. /*--------------------------------------------------------------------*/
  89. /*                        Internal prototypes                         */
  90. /*--------------------------------------------------------------------*/
  91.  
  92. static void modemControl( char mask, boolean on);
  93. static void ShowModem( void );
  94. static unsigned char bps_table(int);
  95.  
  96. /*--------------------------------------------------------------------*/
  97. /*                          Global variables                          */
  98. /*--------------------------------------------------------------------*/
  99.  
  100. static BPS currentBPS;
  101. static char currentDirect;
  102. static boolean carrierDetect;
  103.  
  104. currentfile();
  105. static boolean hangupNeeded = TRUE;
  106.  
  107.  
  108. /*--------------------------------------------------------------------*/
  109. /*    b p s _ t a b l e                                               */
  110. /*                                                                    */
  111. /*    Look up the INT14 baud rate value corresponding to (bps).       */
  112. /*--------------------------------------------------------------------*/
  113.  
  114. static unsigned char bps_table (int bps)
  115. {
  116.  
  117.    static int tab[] = {110, 150, 300, 600, 1200, 2400, 4800, 9600, -1};
  118.    unsigned char i;
  119.  
  120.    for (i = 0; tab[i] > 0; i++)
  121.    {
  122.       if (tab[i] == bps)
  123.          return i;
  124.    }
  125.  
  126.    return 255;
  127.  
  128. } /* bps_table */
  129.  
  130. /*--------------------------------------------------------------------*/
  131. /*    i o p e n l i n e                                               */
  132. /*                                                                    */
  133. /*    Open the serial port for I/O                                    */
  134. /*--------------------------------------------------------------------*/
  135.  
  136. int iopenline(char *name, BPS bps, const boolean direct)
  137. {
  138.  
  139.    if (portActive)              /* Was the port already active?      */
  140.       closeline();               /* Yes --> Shutdown it before open  */
  141.  
  142.    printmsg(15, "openline: %s, %lu", name, bps);
  143.  
  144.    currentDirect = (char) (direct ? 'D' : 'M');
  145.  
  146.    if (sscanf(name, "COM%d", &portNum) != 1)
  147.    {
  148.       printmsg(0,"Communications port must be format COMx, was %s",
  149.                 name);
  150.       panic();
  151.    }
  152.  
  153.    norecovery = FALSE;     // Flag we need a graceful shutdown after
  154.                            // Cntl-BREAK
  155.  
  156. /*--------------------------------------------------------------------*/
  157. /*       With the INT14 setup, we don't worry about the lock file     */
  158. /*       since our modem sharing software is supposed to deal with    */
  159. /*       resource contention.                                         */
  160. /*--------------------------------------------------------------------*/
  161.  
  162.    portNum--;              /* Change ordinal number to offset       */
  163.    SIOSpeed( bps );        /* Open the port and set the speed       */
  164.    flowcontrol( FALSE );   /* Enable hardware flow control          */
  165.  
  166.    ssleep(2);              /* Wait two seconds as required by V.24  */
  167.    carrierDetect = FALSE;  /* No modem connected yet                */
  168.  
  169.    traceStart( name );
  170.  
  171.    portActive = TRUE;     /* record status for error handler */
  172.  
  173.    return 0;               // Return success to caller
  174.  
  175. } /* iopenline */
  176.  
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*    i s r e a d                                                     */
  180. /*                                                                    */
  181. /*    Read from the serial port                                       */
  182. /*                                                                    */
  183. /*    Non-blocking read essential to "g" protocol.  See               */
  184. /*    "dcpgpkt.c" for description.  This all changes in a             */
  185. /*    multi-tasking system.  Requests for I/O should get queued       */
  186. /*    and an event flag given.  Then the requesting process (e.g.     */
  187. /*    gmachine()) waits for the event flag to fire processing         */
  188. /*    either a read or a write.  Could be implemented on VAX/VMS      */
  189. /*    or DG but not MS-DOS.                                           */
  190. /*--------------------------------------------------------------------*/
  191.  
  192. unsigned int isread(char *buffer, unsigned int wanted, unsigned int timeout)
  193. {
  194.  
  195.    union REGS regs;          /* Scratch area for interrupt calls. */
  196.  
  197.    /* With INT14, don't bother with a counter; just set a timeout    */
  198.    /*  value with INT14/AX=8009.  This is Artisoft-specific.         */
  199.  
  200.    int count = 0;
  201.  
  202.    ShowModem();                  // Report modem status
  203.  
  204. /*--------------------------------------------------------------------*/
  205. /*             Now actually try to read a buffer of data              */
  206. /*--------------------------------------------------------------------*/
  207.  
  208.    regs.x.ax = 0x8009;            /* Set timeouts */
  209.    regs.x.bx = timeout * 91 / 5;  /* Send timeout in ticks */
  210.    regs.x.cx = timeout * 91 / 5;  /* Receive timeout in ticks */
  211.    regs.x.dx = portNum;           /* Port number */
  212.    int86 (FS_INTERRUPT, ®s, ®s);
  213.  
  214.    for ( count = 0; count < (int) wanted; count++ )
  215.    {
  216.       unsigned short result = FossilCntl( FS_RECV1, 0);
  217.  
  218.       if (result & 0x8000)          // Did read time out?
  219.       {
  220.          printmsg (20, "Timeout in sread().");
  221.          traceData( buffer, count + 1, FALSE );
  222.          return count;
  223.       }
  224.  
  225.       buffer[count] = (char) (result & 0x00ff);
  226.    }
  227.  
  228.    traceData( buffer, count + 1, FALSE );
  229.    return count + 1;
  230.  
  231. } /* isread */
  232.  
  233. /*--------------------------------------------------------------------*/
  234. /*    i s w r i t e                                                   */
  235. /*                                                                    */
  236. /*    Write to the serial port                                        */
  237. /*--------------------------------------------------------------------*/
  238.  
  239. int iswrite(char *data, unsigned int len)
  240. {
  241.    unsigned int i;
  242.  
  243.    ShowModem();
  244.  
  245. /*--------------------------------------------------------------------*/
  246. /*       For an INT14 interface, just spit the data bytes out one     */
  247. /*       at a time.                                                   */
  248. /*--------------------------------------------------------------------*/
  249.  
  250.    for (i = 0; i < len; i++)
  251.       FossilCntl( FS_XMIT1, data[i] );
  252.  
  253.    traceData( data, len, TRUE );
  254.  
  255. /*--------------------------------------------------------------------*/
  256. /*              Return byte count transmitted to caller               */
  257. /*--------------------------------------------------------------------*/
  258.  
  259.    return len;
  260.  
  261. } /* iswrite */
  262.  
  263. /*--------------------------------------------------------------------*/
  264. /*    i s s e n d b r k                                               */
  265. /*                                                                    */
  266. /*    Send a break signal out the serial port                         */
  267. /*--------------------------------------------------------------------*/
  268.  
  269. void issendbrk(unsigned int duration)
  270. {
  271.    printmsg(12, "ssendbrk: %d", duration);
  272.  
  273. /*--------------------------------------------------------------------*/
  274. /*       With INT14, we drop DSR for a quarter of a second to         */
  275. /*       indicate a BREAK sequence.                                   */
  276. /*                                                                    */
  277. /*       (Snuffles doubts this works properly)                        */
  278. /*--------------------------------------------------------------------*/
  279.  
  280.    modemControl( 0x20, TRUE );   // Raise flag, which lowers DSR
  281.  
  282.    ddelay (250);                 // Wait a quarter second
  283.  
  284.    modemControl( 0x20, FALSE);   // Lower flag, which raises DSR
  285.  
  286. } /* issendbrk */
  287.  
  288.  
  289. /*--------------------------------------------------------------------*/
  290. /*    i c l o s e l i n e                                             */
  291. /*                                                                    */
  292. /*    Close the serial port down                                      */
  293. /*--------------------------------------------------------------------*/
  294.  
  295. void icloseline(void)
  296. {
  297.    if (!portActive)
  298.       panic();
  299.  
  300.    portActive = FALSE;     /* flag port closed for error handler  */
  301.  
  302.    modemControl( 0x20, FALSE );  // Lower DSR
  303.  
  304.    ddelay (500);
  305.  
  306.    traceStop();
  307.  
  308. } /* icloseline */
  309.  
  310.  
  311. /*--------------------------------------------------------------------*/
  312. /*    i h a n g u p                                                   */
  313. /*                                                                    */
  314. /*    Hangup the telephone by dropping DTR.                           */
  315. /*--------------------------------------------------------------------*/
  316.  
  317. void ihangup( void )
  318. {
  319.    if (!hangupNeeded)
  320.       return;
  321.    hangupNeeded = FALSE;
  322.  
  323.    modemControl( 0x20, FALSE );  // Lower DSR
  324.  
  325.    ddelay (500);                 /* Pause half a second */
  326.  
  327.    modemControl( 0x20, TRUE );   // Restore DSR
  328.  
  329.    ddelay (2000);                /* Wait two seconds to recover */
  330.  
  331.    printmsg(3,"hangup: complete.");
  332.    carrierDetect = FALSE;  /* No modem connected yet               */
  333.  
  334. } /* ihangup */
  335.  
  336. /*--------------------------------------------------------------------*/
  337. /*    i S I O S p e e d                                               */
  338. /*                                                                    */
  339. /*    Re-specify the speed of an opened serial port                   */
  340. /*--------------------------------------------------------------------*/
  341.  
  342. void iSIOSpeed(BPS bps)
  343. {
  344.    union REGS regs;          /* Scratch area for interrupt calls. */
  345.  
  346.    regs.h.ah = 0x00;            /* Initialize modem */
  347.    regs.x.ax = 0x0400;          /* Initialize port */
  348.    regs.h.bh = 0x00;            /* No parity */
  349.    regs.h.bl = 0x00;            /* One stop bit */
  350.    regs.h.ch = 0x03;            /* Eight-bit words */
  351.    regs.h.cl = bps_table(bps);  /* New baud rate */
  352.    regs.x.dx = portNum;
  353.    int86 (FS_INTERRUPT, ®s, ®s);
  354.  
  355.    ShowModem();
  356.    currentBPS = bps;
  357.  
  358. } /* iSIOSpeed */
  359.  
  360. /*--------------------------------------------------------------------*/
  361. /*    i f l o w c o n t r o l                                         */
  362. /*                                                                    */
  363. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  364. /*--------------------------------------------------------------------*/
  365.  
  366. void iflowcontrol( boolean flow )
  367. {
  368.  
  369.    union REGS regs;          /* Scratch area for interrupt calls. */
  370.  
  371. /*
  372.    With INT14, don't open and close the port; toggle it in place
  373.    by using INT14/AX=800A, which is again Artisoft-specific.
  374. */
  375.    printmsg (4, "flowcontrol: %abling in-band flow control",
  376.                               (flow ? "en" : "dis"));
  377.    regs.x.ax = 0x800A;
  378.    regs.h.bl = (unsigned char) (flow ? 2 : 1);
  379.                                  // 2 is hardware, 1 is XON/XOFF
  380.    regs.x.dx = portNum;
  381.    int86 (FS_INTERRUPT, ®s, ®s);
  382.  
  383.    ShowModem();
  384.  
  385. } /* iflowcontrol */
  386.  
  387. /*--------------------------------------------------------------------*/
  388. /*    i G e t S p e e d                                               */
  389. /*                                                                    */
  390. /*    Report current speed of communications connection               */
  391. /*--------------------------------------------------------------------*/
  392.  
  393. BPS iGetSpeed( void )
  394. {
  395.    return currentBPS;
  396. } /* GetSpeed */
  397.  
  398. /*--------------------------------------------------------------------*/
  399. /*    i C D                                                           */
  400. /*                                                                    */
  401. /*    Report if we have carrier detect and lost it                    */
  402. /*--------------------------------------------------------------------*/
  403.  
  404. #define FS_dsr_high() (FSStatus() & MDM_DSR)
  405. #define FS_cd_high()  (FSStatus() & MDM_CD )
  406.  
  407. boolean iCD( void )
  408. {
  409.    boolean online = carrierDetect;
  410.  
  411.    ShowModem();
  412.    carrierDetect = FS_cd_high();
  413.  
  414. /*--------------------------------------------------------------------*/
  415. /*    If we previously had carrier detect but have lost it, we        */
  416. /*    report it was lost.  If we do not yet have carrier detect,      */
  417. /*    we return success because we may not have connected yet.        */
  418. /*--------------------------------------------------------------------*/
  419.  
  420.    if (online)
  421.       return carrierDetect && FS_dsr_high();
  422.    else
  423.       return FS_dsr_high();
  424.  
  425. } /* iCD */
  426.  
  427. /*--------------------------------------------------------------------*/
  428. /*    S h o w M o d e m                                               */
  429. /*                                                                    */
  430. /*    Report current modem status                                     */
  431. /*--------------------------------------------------------------------*/
  432.  
  433. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  434.  
  435. static void ShowModem( void )
  436. {
  437.    static int oldStatus = 0xDEAD;
  438.    int status;
  439.  
  440.    if ( debuglevel < 4 )
  441.       return;
  442.  
  443.    status = FSStatus();
  444.  
  445.    if (status == oldStatus)
  446.       return;
  447.  
  448.    printmsg(0, "ShowModem: %#02x%s%s%s%s%s%s%s%s",
  449.       status,
  450.       mannounce(MDM_CD,   status, "\tCarrier Detect"),
  451.       mannounce(MDM_RI,   status, "\tRing Indicator"),
  452.       mannounce(MDM_DSR,  status, "\tData Set Ready"),
  453.       mannounce(MDM_CTS,  status, "\tClear to Send"),
  454.       mannounce(MDM_CDC,  status, "\tCD changed"),
  455.       mannounce(MDM_TRI,  status, "\tRI went OFF"),
  456.       mannounce(MDM_DSRC, status, "\tDSR changed"),
  457.       mannounce(MDM_CTSC, status, "\tCTS changed"));
  458.  
  459.    oldStatus = status;
  460.  
  461. } /* ShowModem */
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*       m o d e m C o n t r o l                                      */
  465. /*                                                                    */
  466. /*       Twiddle a modem control register bit on or off               */
  467. /*--------------------------------------------------------------------*/
  468.  
  469. static void modemControl( char mask, boolean on)
  470. {
  471.    union REGS regs;              /* Scratch area for interrupt calls. */
  472.  
  473.    regs.x.ax = 0x0500;           /* Extended port control: get modem
  474.                                     control register                  */
  475.    regs.x.dx = portNum;
  476.    int86(FS_INTERRUPT, ®s, ®s);
  477.  
  478.    regs.x.ax = 0x0501;           /* Set modem control register */
  479.    regs.x.dx = portNum;
  480.    if ( on )
  481.       regs.h.bl |= mask;         /* Raise flag */
  482.    else
  483.       regs.h.bl &= ~ mask;       /* Lower flag */
  484.  
  485.    int86(FS_INTERRUPT, ®s, ®s);
  486.  
  487. } /* modemControl */
  488.